<?

/**
 * MailMail class
 *
 * Esta clase maneja los Mails Mime
 * @author Alejandro Garcia del Rio <alejandro.garciadelrio@elserver.com>
 * @version 1.0
 * @package MailMail
*/

require_once 'Mail/mimeDecode.php';

class MailMime extends Core {

	static protected $instancia;
	static protected $opciones = array();
	private $attachments = array();
	private $charset = array();
	private $encoding = array();
	private $contentype = array();
	private $subject = null;
	private $text = null;
	private $html = null;
	private $headers = array();
	private $folder = '/tmp/'; // Carpeta de almacenamiento temporal (para adjuntos)

	/**
	 * Constructor de la clase.
	 * 
	 * @param integer $id_caso (opcional) El id de caso al que pertenecen estos tags
	 * @param array $opciones (opcional) Opciones validas para esta clase
	 */
	function __construct ($opciones=null) {
		// Llamo al constructor del parent tambien
		parent::__construct();
		// Guardo las opciones si me definio alguna
		if ($opciones)
			$this->opciones($opciones);

		// Hago absoluta la carpeta de temporales
		//$this->folder = CONFIG_DOCUMENT_ROOT.$this->folder;
	}

	/**
	 * Setea las opciones 
	 * 
	 * @param array $opciones (opcional) Opciones validas para esta clase. Si esta vacio, funciona como un getter.
	 * @return array $opciones Listado de opciones
	 */
	public function opciones ($opciones=null) {
		return self::$opciones = parent::opciones(self::$opciones, $opciones);
	}

	/**
	 * Devuelve una unica instancia de esta clase
	 * 
	 * @return object Instancia de esta clase
	 */
	public static function getInstance() {
		if (!self::$instancia instanceof self)
			self::$instancia = new self;
		return self::$instancia;
	}

	/**
	 * Carga un mime mail.
	 * 
	 * @param string $mailmime Contenido de un mail mime
	 * @return boolean
	 */
	function load($mailmime) {

		// Reinicio las variables
		$this->attachments = array();
		$this->headers = array();
		$this->subject = null;
		$this->text = null;
		$this->html = null;
		$this->charset = null;

		// Defino params
		$params['include_bodies'] = true;
		$params['decode_bodies']  = true;
		$params['decode_headers'] = true;
//		$params['crlf'] = "\r\n\r\n";
		$params['input'] = $mailmime;

/*
$pepe = preg_split("/\r\n\r\n|\r\n\r/is", $params['input']);
echo '<pre>PEPE: '.print_r($pepe, true).'====PEPE====</pre>';

foreach ($pepe as $i => $val) {
	echo '<pre>First Character ['.$i.'] "'.$pepe[$i].'": '.ord($pepe[$i]).'</pre>';
	echo '<pre>Last Character ['.$i.'] "'.$pepe[$i].'": '.ord(substr($pepe[$i], -1, 1)).'</pre>';
}

echo '<pre><strong>MAIMLIME DECODE ANTES:</strong></pre>';
echo '<pre>'.$params['input'].'</pre>';
*/
		// Decodifico el contenido del mail mime
		$content = Mail_mimeDecode::decode($params);

//echo '<pre><strong>MAIMLIME DECODE DESPUES:</strong></pre>';
//echo '<pre>'.print_r($content, true).'</pre>';

		// Proceso los encabezados
		if ($content->headers)
			foreach ($content->headers as $k => $v)
				$this->headers[strtolower($k)] = is_array($v)? implode("\n", $v) : $v;

		// Obtengo el subject
		$this->subject = $this->headers['subject'];

		// Si no hay parts, las simulo con el contenido del mail
		if (!$content->parts)
			$this->part($content);
		else
			foreach ($content->parts as $part)
				$this->part($part);

		return true;
	}

	/**
	 * Carga una parte de un mail mime
	 * 
	 * @param string $part Part de un mail mime
	 * @return boolean
	 */
	function part ($part) {
//echo "part: \n".print_r($part, true);



		// Almaceno el charset
		if ($part->ctype_parameters && $part->ctype_parameters['charset'])
			$charset = preg_replace('/^(.+?)([^a-zA-Z0-9\-].+)/i', '\\1', $part->ctype_parameters['charset'], 1);
		$this->charset[$part->ctype_primary][$part->ctype_secondary] = $charset;

		// Almaceno el encoding
		if ($part->headers['content-transfer-encoding'])
			$encoding = preg_replace('/^(.+?)([^a-zA-Z0-9\-].+)/i', '\\1', $part->headers['content-transfer-encoding'], 1);
		$this->encoding[$part->ctype_primary][$part->ctype_secondary] = $encoding;

		// Almaceno el content type
		if ($part->headers['content-transfer-encoding'])
			$encoding = preg_replace('/^(.+?)([^a-zA-Z0-9\-].+)/i', '\\1', $part->headers['content-transfer-encoding'], 1);
		$this->encoding[$part->ctype_primary][$part->ctype_secondary] = $encoding;

		// Es un attachment
		if (($part->disposition == 'attachment') || (strstr('attachment', $part->headers['content-disposition'])) )
			return $this->attachment($part);

		// Es un multipart, nos volvemos a llamar recursivamente
		if (($part->ctype_primary == 'multipart') && $part->parts)
			foreach ($part->parts as $p)
				$this->part($p);


		// Es texto, me fijo si es plain o html
		if ($part->ctype_primary == 'text') {

			// Trato de desencodear el contenido
			//if ( ($function = preg_replace('/\-/', '_', $encoding)."_decode") && function_exists($function) && !empty($part->body) )
			//	$part->body = $function($part->body);

//echo '<pre>PART HEADERS: '.print_r($part->headers, true).'</pre>';
			// Si es base64, lo convierto
			if ($part->headers['content-transfer-encoding'] == 'base64') {

/*
echo '<pre>========================================</pre>';
echo '<pre>Base 64!!!!</pre>';
echo '<pre>PART: '.print_r($part, true).'</pre>';
echo '<pre>ORIGINAL: '.$part->body.'</pre>';
echo '<pre>CONVERTIDO: '.base64_decode($part->body).'</pre>';
echo '<pre>========================================</pre><br /><br />';
//				$part->body = base64_decode($part->body);
*/
			}

			// Es el contenido en formato texto
			 if ($part->ctype_secondary == 'plain') {
				return $this->text = $part->body;
			}

			// Es el contenido en formato html
			if ($part->ctype_secondary == 'html') {
				return $this->html = str_replace('&nbsp;', '', $part->body);
			}
		}

		return false;
	}

	/**
	 * Agrega un nuevo attachment a este mail mime
	 * 
	 * @param string $attachment Part de un mail mime con content-disposition: attachment
	 * @return array
	 */
	function attachment ($part) {

//echo '<pre>Attachment: '.print_r($part, true).'</pre>';

		// Archivo temporal de destino
		if (!$new_file = $part->ctype_parameters['name'])
			if ( !($new_file = $part->d_parameters['filename']) && 
				 preg_match('/filename="?([^"]+)"?/', $part->headers['content_disposition'], $matches) )
				$new_file = $matches[1];

		$new_file = $this->folder.$new_file;

		// Contenido del archivo
		$content = $part->body;

		// Creo el archivo temporal
		file_put_contents($new_file, $content);

		// Agrego el adjunto al array de adjuntos
		$this->attachments[] = $new_file;

		return true;
	}

	/**
	 * Devuelve el listado de archivos adjuntos de este mail mime
	 * 
	 * @return array
	 */
	function attachments () {
		return $this->attachments;
	}

	/**
	 * Devuelve el listado de encabezados
	 * 
	 * @return array
	 */
	function headers () {
		return $this->headers;
	}

	/**
	 * Devuelve el cuerpo del mail en formato texto plano
	 * 
	 * @return array
	 */
	function text () {

		// Si solo tengo html, creo el text en base al html
		if (!$this->text && $this->html)
			$this->text = strip_tags($this->html);

		return nl2br($this->text);
	}

	/**
	 * Devuelve el cuerpo del mail en formato html (si existe)
	 * 
	 * @return array
	 */
	function html () {

		return $this->html;
	}

	/**
	 * Devuelve el resumen del contenido del mail
	 * 
	 * @return array
	 */
	function summary () {
		return substr(preg_replace('/ +/', ' ', strip_tags($this->text())), 0, 200);
	}

	/**
	 * Devuelve el asunto del mail
	 * 
	 * @return array
	 */
	function subject () {
		return $this->subject;
	}

	/**
	 * Devuelve el charset de este mail mime para el tipo solicitado ('text/html' o 'text/plain')
	 * 
	 * @param $type string Tipo de parte para el que se quiere el charset ('text/html' o 'text/plain');
	 * @return string
	 */
	function charset ($type='text/plain') {
		$types = explode('/', $type);
//		return ($this->charset[$types[0]][$types[1]])? $this->charset[$types[0]][$types[1]] : $this->charset['text']['html'];
		return ($this->charset[$types[0]][$types[1]])? $this->charset[$types[0]][$types[1]] : false;
	}

	/**
	 * Devuelve el content type de este mail mime para el tipo solicitado ('text/html' o 'text/plain')
	 * 
	 * @param $type string Tipo de parte para el que se quiere el encoding ('text/html' o 'text/plain');
	 * @return string
	 */
	function contentype ($type='text/plain') {
		$types = explode('/', $type);
//		return ($this->encoding[$types[0]][$types[1]])? $this->encoding[$types[0]][$types[1]] : $this->encoding['text']['html'];
		return ($this->encoding[$types[0]][$types[1]])? $this->encoding[$types[0]][$types[1]] : false;
	}

	/**
	 * Devuelve el content type de este mail mime para el tipo solicitado ('text/html' o 'text/plain')
	 * 
	 * @param $type string Tipo de parte para el que se quiere el encoding ('text/html' o 'text/plain');
	 * @return string
	 */
	function encoding () {
		$types = explode('/', $type);
//		return ($this->encoding[$types[0]][$types[1]])? $this->encoding[$types[0]][$types[1]] : $this->encoding['text']['html'];
		return ($this->encoding[$types[0]][$types[1]])? $this->encoding[$types[0]][$types[1]] : false;
	}

}
?>
